﻿using CIS.Web.Common;
using CIS.Web.Models;
using CIS.Web.Properties;
using System;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Linq.Dynamic;
using System.Net.Mail;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace CIS.Web.Controllers
{
	[RoutePrefix("ConferenceVisa")]
	public class ConferenceVisaController : BaseDbController
	{
		[Route("Index/{ConferenceId}")]
		public async Task<ActionResult> Index(string conferenceId)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", conferenceId);

			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.Status == ConstValues.Status.正常 &&
						x.ID == conferenceId);

			ViewBag.ConferenceId = conferenceId;
			ViewBag.ConferenceName = conferenceMaster.ConferenceName;
			ViewBag.ControllerName = Resources.ConferenceVisa;
			ViewBag.Language = conferenceMaster.IsInternational ? ConstValues.Language.En : ConstValues.Language.Cn;

			var model = new ProfileVisaModel();
			model.ConferenceId = conferenceId;
			LoginUser.ConferenceFunctionIdList = Utility.GetConferenceFunctionIdList(conferenceId);
			return View(model);
		}

		public async Task<JsonCamelCaseResult> GetData(int? page, int? rows, string sort, string order, ProfileVisaModel model)
		{
			int take = rows ?? ConstValues.DefaultGridRows;
			int skip = ((page ?? 1) - 1) * take;

			var sql = from visaInfo in DbContext.VisaInfo.AsNoTracking().Where(x => !string.IsNullOrEmpty(x.Status))
				  join attendInfo in DbContext.ConferenceAttendenceInfo.AsNoTracking().Where(x => x.ConferenceId == model.ConferenceId)
					on visaInfo.AttendenceId equals attendInfo.ID
				  join titleInfo in DbContext.TitleMaster.AsNoTracking()
					on visaInfo.Title equals titleInfo.ID into titles
				  from title in titles.DefaultIfEmpty()
				  join countryInfo in DbContext.LocationMaster.AsNoTracking().Where(x => x.Level == ConstValues.LocationLevel.国家)
					on visaInfo.Country equals countryInfo.ID into countrys
				  from country in countrys.DefaultIfEmpty()
				  orderby attendInfo.Sort ascending, attendInfo.UpdateDate descending
				  select new
				  {
					  FamilyName = visaInfo.FamilyName,
					  FirstName = visaInfo.FirstName,
					  Title = title.TitleName,
					  Affiliation = visaInfo.Affiliation,
					  Address = visaInfo.Address,
					  City = visaInfo.CityStr,
					  State = visaInfo.StateStr,
					  ZipCode = visaInfo.ZipCode,
					  Country = country.Name,
					  CountryEn = country.NameEn,
					  Mail = visaInfo.Mail,
					  Telephone = visaInfo.Telephone,
					  Birthdate = visaInfo.Birthdate,
					  Gender = visaInfo.Gender,
					  PassportNum = visaInfo.PassportNum,
					  IssueOfCountry = visaInfo.IssueOfCountry,
					  DateOfIssue = visaInfo.DateOfIssue,
					  ExpiryDate = visaInfo.ExpiryDate,
					  ArrivalDate = visaInfo.ArrivalDate,
					  DeparturalDate = visaInfo.DeparturalDate,
					  SendStatus = visaInfo.SendStatus,
					  Status = visaInfo.Status,
					  Remark = visaInfo.Remark,
					  Creator = visaInfo.Creator,
					  CreateIP = visaInfo.CreateIP,
					  CreateDate = visaInfo.CreateDate,
					  Sort = attendInfo.Sort,
					  ID = visaInfo.ID,
					  AttendenceId = visaInfo.AttendenceId,
					  ConferenceId = attendInfo.ConferenceId,
					  Invitation = visaInfo.Invitation
				  };

			if (!string.IsNullOrWhiteSpace(model.SelUserName))
			{
				sql = sql.Where(x => x.FamilyName.Contains(model.SelUserName) || x.FirstName.Contains(model.SelUserName));
			}

			int total = await sql.CountAsync();

			if (!string.IsNullOrEmpty(sort))
			{
				sql = sql.OrderBy(sort + ConstValues.chrSpace + order).Skip(skip).Take(take);
			}
			else
			{
				sql = sql.OrderBy(x => x.Sort).ThenByDescending(x => x.CreateDate).ThenBy(x => x.FamilyName).Skip(skip).Take(take);
			}

			var sqlResult = await sql.ToListAsync();

			var result = sqlResult.Select(x => new
			{
				ID = x.ID,
				AttendenceId = x.AttendenceId,
				ConferenceId = x.ConferenceId,
				FamilyName = x.FamilyName,
				FirstName = x.FirstName,
				Title = x.Title,
				Affiliation = x.Affiliation,
				Address = x.Address,
				City = x.City,
				State = x.State,
				ZipCode = x.ZipCode,
				Country = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ? x.Country : x.CountryEn,
				Mail = x.Mail,
				Invitation = string.IsNullOrEmpty(x.Invitation) ? string.Empty : ConstValues.SystemWeb + x.Invitation.Replace(ConstValues.strWave, string.Empty),
				Telephone = x.Telephone,
				Birthdate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.Birthdate.Value.ToString("yyyy-MM-dd") :
							x.Birthdate.Value.ToString("MM/dd/yyyy"),
				Gender = x.Gender.Value ? Resources.Male : Resources.Female,
				PassportNum = x.PassportNum,
				IssueOfCountry = x.IssueOfCountry,
				DateOfIssue = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.DateOfIssue.Value.ToString("yyyy-MM-dd") :
							x.DateOfIssue.Value.ToString("MM/dd/yyyy"),
				ExpiryDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.ExpiryDate.Value.ToString("yyyy-MM-dd") :
							x.ExpiryDate.Value.ToString("MM/dd/yyyy"),
				ArrivalDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.ArrivalDate.Value.ToString("yyyy-MM-dd") :
							x.ArrivalDate.Value.ToString("MM/dd/yyyy"),
				DeparturalDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.DeparturalDate.Value.ToString("yyyy-MM-dd") :
							x.DeparturalDate.Value.ToString("MM/dd/yyyy"),
				Status = x.SendStatus == ConstValues.SendStatus.已发送 ? x.SendStatus : x.Status,
				Remark = x.Remark,
				Creator = x.Creator,
				CreateIP = x.CreateIP,
				CreateDate = Request.Cookies["_culture"].Value == ConstValues.Language.Cn ?
							x.CreateDate.Value.ToString("yyyy-MM-dd") :
							x.CreateDate.Value.ToString("MM/dd/yyyy")
			});

			return JsonCamelCase(new
			{
				Total = total,
				Rows = result,
			},
			JsonRequestBehavior.AllowGet);
		}

		public async Task<JsonCamelCaseResult> GetVisaData(string attendId)
		{
			var sqlResult = await DbContext.VisaInfo.AsNoTracking().FirstOrDefaultAsync(x => x.AttendenceId == attendId);

			if (sqlResult == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}

			var result = new
			{
				familyName = sqlResult.FamilyName,
				firstName = sqlResult.FirstName,
				title = DbContext.TitleMaster.AsNoTracking().FirstOrDefault(x => x.ID == sqlResult.Title)?.ID,
				affiliation = sqlResult.Affiliation,
				address = sqlResult.Address,
				country = DbContext.LocationMaster.AsNoTracking().FirstOrDefault(x => x.ID == sqlResult.Country)?.ID,
				state = sqlResult.StateStr,
				city = sqlResult.CityStr,
				zipCode = sqlResult.ZipCode,
				mail = sqlResult.Mail,
				tele = sqlResult.Telephone,
				birthday = Utility.SetDate(sqlResult.Birthdate, Request.Cookies["_culture"].Value),
				gender = sqlResult.Gender,
				passportNum = sqlResult.PassportNum,
				issueOfCountry = sqlResult.IssueOfCountry,
				dateOfIssue = Utility.SetDate(sqlResult.DateOfIssue, Request.Cookies["_culture"].Value),
				expiryDate = Utility.SetDate(sqlResult.ExpiryDate, Request.Cookies["_culture"].Value),
				arrivalDate = Utility.SetDate(sqlResult.ArrivalDate, Request.Cookies["_culture"].Value),
				departuralDate = Utility.SetDate(sqlResult.DeparturalDate, Request.Cookies["_culture"].Value),
				remark = sqlResult.Remark,
			};

			return JsonCamelCase(Utility.CreateSuccessJsonResult(string.Empty, result),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[Route("Delete/{ConferenceId}")]
		public async Task<JsonResult> Delete(ProfileVisaModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var result = await DbContext.VisaInfo.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.MsgRecordNotExist),
						JsonRequestBehavior.AllowGet);
			}

			DbContext.VisaInfo.Remove(result);

			var attendInfo = await DbContext.ConferenceAttendenceInfo.FirstOrDefaultAsync(x => x.ID == model.AttendenceId);
			attendInfo.HasVisa = false;

			await DbContext.SaveChangesAsync();

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessDelete),
					JsonRequestBehavior.AllowGet);
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[ValidateInput(false)]
		[Route("Upload/{ConferenceId}")]
		public async Task<JsonResult> Upload(ProfileVisaModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var result = await DbContext.VisaInfo.FirstOrDefaultAsync(x => x.ID == model.Id);

			if (result == null)
			{
				string errorMessage = Resources.MsgRecordNotExist;
				return JsonCamelCase(Utility.CreateFailJsonResult(errorMessage),
						JsonRequestBehavior.AllowGet);
			}

			if (model.InvitationFile != null)
			{
				var msg = await this.SaveFiles(model);
				if (!string.IsNullOrEmpty(msg))
				{
					return JsonCamelCase(Utility.CreateFailJsonResult(msg),
							JsonRequestBehavior.AllowGet);
				}
			}

			result.Invitation = model.InvitationFilePath;
			result.Updater = LoginUser.UserName;
			result.UpdateIP = LoginUser.IP;
			result.UpdateDate = DateTime.Now;

			await DbContext.SaveChangesAsync();

			return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSubmit),
					JsonRequestBehavior.AllowGet);
		}

		private async Task<string> SaveFiles(ProfileVisaModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var result = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID == model.ConferenceId);

			if (model.InvitationFile != null)
			{
				if (model.InvitationFile.ContentLength > ConstValues.FileMaxLength)
				{
					return Resources.MsgFileOverflowError;
				}

				string nickName = DbContext.ConferenceMaster.AsNoTracking().FirstOrDefault(x => x.ID == model.ConferenceId)?.ConferenceNickName;
				string folder = Path.Combine(ConstValues.Uploads, nickName);
				string pfolder = Path.Combine(Server.MapPath(ConstValues.Uploads), nickName);

				string fileName = nickName + ConstValues.strHyphen +
						Path.GetExtension(model.InvitationFile.FileName).Replace(".", "").ToUpper() + ConstValues.strHyphen +
						DateTime.Now.ToString("yyyy") + ConstValues.strHyphen +
						Utility.GetRandom() + Path.GetExtension(model.InvitationFile.FileName);
				model.InvitationFilePath = Path.Combine(folder, fileName);
				var saveFileTask = Task.Run(() =>
				{
					var pFullPath = Path.Combine(pfolder, fileName);
					if (!Directory.Exists(pfolder))
					{
						Directory.CreateDirectory(pfolder);
					}
					model.InvitationFile.SaveAs(pFullPath);
				});
				Task.WaitAll(saveFileTask);
			}

			return string.Empty;
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		[ValidateInput(false)]
		[Route("SendMail/{ConferenceId}")]
		public async Task<JsonResult> SendMail(ProfileVisaModel model)
		{
			string controller = RouteData.Values["controller"].ToString();
			string actionName = RouteData.Values["action"].ToString();
			Utility.InsertLog(LoginUser, Request.Url.ToString(), controller, actionName, "Index", model.ConferenceId);

			var conferenceMailServerMaster = await DbContext.ConferenceMailServerMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.Status == ConstValues.Status.正常 &&
						x.MailType == ConstValues.MailType.会议邮箱 &&
						x.ConferenceId == model.ConferenceId);

			if (conferenceMailServerMaster == null)
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.SmtpException_MailServerNotExist),
						JsonRequestBehavior.AllowGet);
			}

			var strMsg = string.Empty;

			var result = await DbContext.VisaInfo.FirstOrDefaultAsync(x => x.ID == model.Id);

			var conferenceMaster = await DbContext.ConferenceMaster.AsNoTracking()
					.FirstOrDefaultAsync(x => x.ID == model.ConferenceId);

			MailSender sender = new MailSender(conferenceMailServerMaster.MailServer);
			MailAddress from = new MailAddress(conferenceMailServerMaster.Mail);
			MailAddress to = new MailAddress(result.Mail);
			MailMessage message = new MailMessage();

			var fileName = Path.GetFileName(result.Invitation);

			var folder = Path.Combine(Server.MapPath(ConstValues.Uploads), conferenceMaster.ConferenceNickName);
			string pdfFilePath = Path.Combine(folder, fileName);
			message.Attachments.Add(new Attachment(pdfFilePath));

			message.Subject = Resources.VisaMailSubject;
			message.Body = Resources.VisaMailContent;
			message.IsBodyHtml = true;
			message.To.Add(to);

			var mailTask = Task.Run(() =>
			{
				var strTmp = sender.SendMail(from, message, conferenceMailServerMaster.Password);
				if (!string.IsNullOrEmpty(strTmp))
				{
					strMsg += "\r\n" + "【" + model.Mail + "】" + strTmp;
				}
			});

			result.SendStatus = ConstValues.SendStatus.已发送;
			await DbContext.SaveChangesAsync();

			if (!string.IsNullOrEmpty(strMsg))
			{
				return JsonCamelCase(Utility.CreateFailJsonResult(Resources.FailSendMail + strMsg),
						JsonRequestBehavior.AllowGet);
			}
			else
			{
				return JsonCamelCase(Utility.CreateSuccessJsonResult(Resources.SuccessSendMail),
						JsonRequestBehavior.AllowGet);
			}
		}

		[AllowAnonymous]
		public async Task<JsonCamelCaseResult> CheckHasVisa(string attendenceId)
		{
			var data = await DbContext.VisaInfo.FirstOrDefaultAsync(x => x.AttendenceId == attendenceId);
			if (data != null)
			{
				var result = new
				{
					HasVisa = true
				};

				return JsonCamelCase(new
				{
					data = result,
					code = "1",
					msg = "success"
				},
				JsonRequestBehavior.AllowGet);
			}
			else
			{
				var result = new
				{
					HasVisa = false
				};

				return JsonCamelCase(new
				{
					data = result,
					code = "1",
					msg = "success"
				},
				JsonRequestBehavior.AllowGet);
			}
		}
	}
}